陣列(Array)是程式設計中最基礎、最常見的資料結構之一。它可以把多筆相同資料型別的資料依序存放在一起,並替每個元素編上索引,讓我們能快速地存取與管理資料。
當程式需要處理大量性質相同的資料時,使用陣列通常會比宣告許多個別變數更簡潔,也更容易搭配迴圈進行計算。
假設今天要記錄五位學生的成績,我們可以先準備五個變數:
int score1 = 80;
int score2 = 90;
int score3 = 75;
int score4 = 60;
int score5 = 85;
只有五筆資料時,好像還不算太麻煩。但是,如果班上有五十位學生,難道要一路宣告到 score50 嗎?後續如果想計算平均成績、找出最高分,或把所有成績印出來,也得逐一操作這些變數,程式會變得很長,而且很難維護。
當我們需要保存許多型態相同、用途相關的資料時,就可以使用陣列。陣列會把這些資料依照順序放在一起,再讓我們透過索引找到其中的元素。
C 語言宣告陣列的基本格式是:
資料型態 陣列名稱[元素數量];
例如,要準備一個能存放五個整數的陣列,可以寫成:
int scores[5];
這行程式的意思是:建立一個名為 scores 的陣列,裡面可以存放五個 int。
陣列也可以在宣告時直接設定初始值:
int scores[5] = {80, 90, 75, 60, 85};
如果已經列出所有初始值,也可以省略中括號裡的數量,讓編譯器自動計算:
int scores[] = {80, 90, 75, 60, 85};
上面兩種寫法都會建立包含五個元素的陣列。
如果只提供部分初始值,其餘元素會自動補成 0:
int scores[5] = {80, 90};
陣列內容會是:
{80, 90, 0, 0, 0}
因此,如果想把全部元素初始化為 0,可以使用:
int scores[5] = {0};
剛開始學習程式語言的陣列時,很容易把陣列的「索引」和「長度」搞混。
陣列會替每個元素編上一個索引,讓程式可以找到指定的位置。C 語言的索引從 0 開始,因此五個元素的索引不是 1 到 5,而是 0 到 4。
先用個簡單的陣列來講解:
int scores[5] = {10, 20, 30, 40, 50};
因為索引是從 0 開始,看起來會像這樣:
索引: 0 1 2 3 4
資料: 10 20 30 40 50
printf("%d\n", scores[0]); // 第一個元素:10
printf("%d\n", scores[3]); // 第四個元素:40
當變數仍是陣列而不是指標時,可以用 sizeof 運算子計算元素數量:
size_t length = sizeof(scores) / sizeof(scores[0]);
printf("陣列長度:%zu\n", length); // 陣列長度:5
也可以透過索引修改元素:
scores[3] = 70;
這行程式會把索引 3,也就是第四個元素,從 40 改成 70。
初學陣列時最容易犯的錯誤,就是把元素數量當成最後一個索引:
int scores[5];
scores[5] = 100; // 錯誤:已超出陣列範圍
scores 只有五個元素,合法索引是 0 到 4。C 語言通常不會自動替我們檢查索引是否超出範圍,越界存取可能修改到其他資料、得到奇怪的結果,甚至造成程式崩潰。因此,使用陣列時一定要特別注意索引範圍。
陣列的一大優點,是可以搭配迴圈統一處理所有元素。例如,把五個成績依序印出來:
#include <stdio.h>
int main(void) {
int scores[5] = {80, 90, 75, 60, 85};
for (int i = 0; i < 5; i++) {
printf("第 %d 位學生:%d 分\n", i + 1, scores[i]);
}
return 0;
}
迴圈中的 i 會依序變成 0、1、2、3、4,剛好對應五個合法索引。條件必須寫成 i < 5,不能寫成 i <= 5,否則最後一次會存取不存在的 scores[5]。
有了迴圈之後,計算總分和平均也很方便:
#include <stdio.h>
int main(void) {
int scores[5] = {80, 90, 75, 60, 85};
int total = 0;
for (int i = 0; i < 5; i++) {
total += scores[i];
}
double average = total / 5.0;
printf("總分:%d\n", total);
printf("平均:%.2f\n", average);
return 0;
}
如果陣列有 n 個元素,走訪全部元素就需要處理 n 次,因此時間複雜度是 O(n)。
陣列可以把多筆相同型態的資料集中管理,並利用從 0 開始的索引存取元素。搭配迴圈後,就能用同一段程式統一處理陣列中的所有資料。
今天的重點:
下一篇會進一步說明陣列在記憶體中如何排列,以及為什麼可以用索引快速找到指定的元素。